#include "StdAfx.h"

Texture* TreeViewItem::m_pPlusTexture = 0;
Texture* TreeViewItem::m_pMinusTexture = 0;
Texture* gTreeHighlight = 0;
CFont* TreeViewItem::m_font = 0;

TreeViewItem::TreeViewItem() : m_pParent(0), m_szText(""), m_isExpanded(false)
{
	m_isHighlighted = false;
	if(!m_pPlusTexture || !m_pMinusTexture)
	{
		m_pPlusTexture = sTexture.GetTexture("Interface\\Buttons\\UI-PlusButton-Up.blp");
		m_pMinusTexture = sTexture.GetTexture("Interface\\Buttons\\UI-MinusButton-Up.blp");
		m_font = new CFont("Fonts\\FrizQT__.ttf", "Friz Quadrata TT", 5, 12);
	}
}

TreeViewItem::TreeViewItem(std::string szName) : m_pParent(0), m_szText(szName), m_isExpanded(false)
{
	m_isHighlighted = false;
	if(!m_pPlusTexture || !m_pMinusTexture)
	{
		m_pPlusTexture = sTexture.GetTexture("Interface\\Buttons\\UI-PlusButton-Up.blp");
		m_pMinusTexture = sTexture.GetTexture("Interface\\Buttons\\UI-MinusButton-Up.blp");
		m_font = new CFont("Fonts\\FrizQT__.ttf", "Friz Quadrata TT", 5, 12);
	}
}

TreeViewItem::TreeViewItem(TreeViewItem *pParent) : m_pParent(pParent), m_szText(""), m_isExpanded(false)
{
	m_isHighlighted = false;
	if(!m_pPlusTexture || !m_pMinusTexture)
	{
		m_pPlusTexture = sTexture.GetTexture("Interface\\Buttons\\UI-PlusButton-Up.blp");
		m_pMinusTexture = sTexture.GetTexture("Interface\\Buttons\\UI-MinusButton-Up.blp");
		m_font = new CFont("Fonts\\FrizQT__.ttf", "Friz Quadrata TT", 5, 12);
	}
}

TreeViewItem::TreeViewItem(TreeViewItem *pParent, std::string szName) : m_pParent(pParent), m_szText(szName), m_isExpanded(false)
{
	m_isHighlighted = false;
	if(!m_pPlusTexture || !m_pMinusTexture)
	{
		m_pPlusTexture = sTexture.GetTexture("Interface\\Buttons\\UI-PlusButton-Up.blp");
		m_pMinusTexture = sTexture.GetTexture("Interface\\Buttons\\UI-MinusButton-Up.blp");
		m_font = new CFont("Fonts\\FrizQT__.ttf", "Friz Quadrata TT", 5, 12);
	}
}

void TreeViewItem::_CalculateVertices(Vertex3FRHWT* pInput, ui32& index)
{
	pInput[0].x = m_position.x;
	pInput[0].y = m_position.y + index * 18;
	pInput[1].x = m_position.x + 16;
	pInput[1].y = m_position.y + index * 18;
	pInput[2].x = m_position.x + 16;
	pInput[2].y = m_position.y + 16 + index * 18;
	pInput[3].x = m_position.x;
	pInput[3].y = m_position.y + 16 + index * 18;
	pInput[0].u = pInput[0].v = pInput[1].v = pInput[3].u = 0.0f;
	pInput[1].u = pInput[2].v = pInput[2].u = pInput[3].v = 1.0f;
}

void TreeViewItem::_Draw(ui32& maxDraw, ui32& curDraw, ui32& scroll)
{
	if(i32(curDraw) - i32(scroll) >= (i32)maxDraw)
		return;

	if(curDraw < scroll)
	{
		++curDraw;
		if(m_isExpanded && i32(curDraw) - i32(scroll) < i32(maxDraw))
		{
			std::set<TreeViewItem*>::iterator itr = m_subItems.begin();
			std::set<TreeViewItem*>::iterator end = m_subItems.end();

			for( ; itr != end; ++itr)
				(*itr)->_Draw(maxDraw, curDraw, scroll);
		}
		return;
	}

	if(m_subItems.size())
	{
		Vertex3FRHWT vertices[4];
		ui32 index = curDraw - scroll;
		_CalculateVertices(vertices, index);
		sD3D->SetFVF(VERTEX3FRHWT);
		if(m_isExpanded)
			sD3D->SetTexture(0, *m_pMinusTexture);
		else
			sD3D->SetTexture(0, *m_pPlusTexture);
		sD3D->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, vertices, sizeof(Vertex3FRHWT));
	}
	if(!gTreeHighlight)
		gTreeHighlight = sTexture.GetTexture("Interface\\Spellbook\\UI-SpellbookPanel-Tab-Highlight.blp");
	
	if(m_isHighlighted)
		_DrawHighlight(m_position.x + 17, m_position.y + (curDraw - scroll) * 18 + 2, m_font->GetTextLen(m_szText, true));

	m_font->DrawTextA(m_position.x + 17, m_position.y + (curDraw - scroll) * 18 + 2, m_font->GetTextLen(m_szText), 30, m_szText);
	++curDraw;

	if(m_isExpanded && i32(curDraw) - i32(scroll) < i32(maxDraw))
	{
		std::set<TreeViewItem*>::iterator itr = m_subItems.begin();
		std::set<TreeViewItem*>::iterator end = m_subItems.end();

		for( ; itr != end; ++itr)
			(*itr)->_Draw(maxDraw, curDraw, scroll);
	}
}

void TreeViewItem::_DrawHighlight(ui32 x, ui32 y, ui32 len)
{
	Vertex3FRHWT hil[4];
	hil[0].x = x - 5;
	hil[1].x = x + len + 3;
	hil[2].x = x + len + 3;
	hil[3].x = x - 5;
	hil[0].y = y - 3;
	hil[1].y = y - 3;
	hil[2].y = y + 17;
	hil[3].y = y + 17;
	hil[0].u = hil[3].u = 15.0f / 128.0f;
	hil[1].u = hil[2].u = 115.0f / 128.0f;
	hil[0].v = hil[1].v = 16.5f / 64.0f;
	hil[2].v = hil[3].v = 43.5f / 64.0f;

	sD3D->SetFVF(VERTEX3FRHWT);
	sD3D->SetTexture(0, *gTreeHighlight);
	sD3D->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, hil, sizeof(Vertex3FRHWT)); 
}

void TreeViewItem::SetPosition(Vertex2F position)
{
	m_position = position;
	std::set<TreeViewItem*>::iterator itr = m_subItems.begin();
	std::set<TreeViewItem*>::iterator end = m_subItems.end();

	for( ; itr != end; ++itr)
		(*itr)->SetPosition(Vertex2F(m_position.x + 8.0f, m_position.y));
}

void TreeViewItem::AddSubItem(TreeViewItem* pItem)
{
	pItem->SetParent(this);
	pItem->m_pTreeView = m_pTreeView;
	pItem->SetPosition(Vertex2F(m_position.x + 8, m_position.y));
	m_subItems.insert(pItem);
}

TreeViewItem* TreeViewItem::AddSubItem(std::string szText)
{
	TreeViewItem* pItem = new TreeViewItem(this, szText);
	AddSubItem(pItem);
	return pItem;
}

void TreeViewItem::SetParent(TreeViewItem* pParent)
{
	m_pParent = pParent;
}

bool TreeViewItem::_CheckSubItems(Vertex2F& pos, ui32& index, ui32& scroll)
{
	if(!m_subItems.size())
	{
		if(index >= scroll && pos.x >= m_position.x + 17 && pos.x <= m_position.x + 17 + m_font->GetTextLen(m_szText)
			&& pos.y >= m_position.y + (index - scroll) * 18 && pos.y <= m_position.y + 16 + (index - scroll) * 18)
		{
			//m_isHighlighted = true;
			return true;
		}
		else
		{
			++index;
			return false;
		}
	}

	if(index >= scroll && pos.x >= m_position.x && pos.x <= m_position.x + 16 &&
		pos.y >= m_position.y + (index - scroll) * 18 && pos.y <= m_position.y + 16 + (index - scroll) * 18)
	{
		m_pTreeView->_OnExpand(index);
		_OnClick();
		return true;
	}

	++index;

	if(!m_subItems.size() || !m_isExpanded)
		return false;

	std::set<TreeViewItem*>::iterator itr = m_subItems.begin();
	std::set<TreeViewItem*>::iterator end = m_subItems.end();

	for(; itr != end; ++itr)
	{
		if(index >= scroll && pos.x >= (*itr)->m_position.x && pos.x <= (*itr)->m_position.x + 16 &&
			pos.y >= (*itr)->m_position.y + (index - scroll) * 18 && pos.y <= (*itr)->m_position.y + (index - scroll) * 18 + 16)
		{
			m_pTreeView->_OnExpand(index);
			(*itr)->_OnClick();
			return true;
		}
		else
		{
			if((*itr)->m_isExpanded && (*itr)->m_subItems.size())
			{
				if((*itr)->_CheckSubItems(pos, index, scroll))
					return true;
			}
			else
			{
				if(!(*itr)->m_subItems.size() && index >= scroll && pos.x >= m_position.x + 17 && pos.x <= m_position.x + 17 + m_font->GetTextLen(m_szText)
					&& pos.y >= m_position.y + (index - scroll) * 18 && pos.y <= m_position.y + 16 + (index - scroll) * 18)
				{
					(*itr)->m_isHighlighted = !(*itr)->m_isHighlighted;
					m_pTreeView->UnhighlightExcept((*itr));
					m_pTreeView->_OnCallback((*itr));
					return true;
				}
				++index;
			}
		}
	}
	return false;
}

ui32 TreeViewItem::_GetNumItems()
{
	if(!m_isExpanded || !m_subItems.size())
		return 1;

	ui32 i = 1;
	std::set<TreeViewItem*>::iterator itr = m_subItems.begin();
	std::set<TreeViewItem*>::iterator end = m_subItems.end();

	for(; itr != end; ++itr)
		i += (*itr)->_GetNumItems();
	return i;

}

ui32 TreeView::GetNumItems()
{
	std::vector<TreeViewItem*>::iterator itr = m_items.begin();
	std::vector<TreeViewItem*>::iterator end = m_items.end();

	ui32 i = 0;
	for( ; itr != end; ++itr)
		i += (*itr)->_GetNumItems();
	return i;
}

void TreeView::AddItem(TreeViewItem* pItem)
{
	pItem->SetPosition(m_position);
	pItem->m_pTreeView = this;
	m_items.push_back(pItem);
}

TreeView::TreeView(ui32 x, ui32 y, ui32 w, ui32 h) : m_curScroll(0)
{
	m_callBack = 0;
	m_pAsyncObject = 0;
	m_position.x = x;
	m_position.y = y;
	m_size.x = w;
	m_size.y = h;
	m_numDraw = floor(h / 18.0f);
}

void TreeView::Draw()
{
	std::vector<TreeViewItem*>::iterator itr = m_items.begin();
	std::vector<TreeViewItem*>::iterator end = m_items.end();

	ui32 i = 0;
	for( ; itr != end; ++itr)
		(*itr)->_Draw(m_numDraw, i, m_curScroll);
}

void TreeView::MouseActivity(bool left, Vertex2F pos, bool up)
{
	if(!up)
		return;

	std::vector<TreeViewItem*>::iterator itr = m_items.begin();
	std::vector<TreeViewItem*>::iterator end = m_items.end();

	ui32 i = 0;
	for( ; itr != end; ++itr)
	{
		if((*itr)->_CheckSubItems(pos, i, m_curScroll))
			return;
	}
}

void TreeView::ModPosition(float x, float y)
{
	m_position.x += x;
	m_position.y += y;

	std::vector<TreeViewItem*>::iterator itr = m_items.begin();
	std::vector<TreeViewItem*>::iterator end = m_items.end();

	for( ; itr != end; ++itr)
		(*itr)->SetPosition(m_position);
}

void TreeView::UnhighlightExcept(TreeViewItem* pItem)
{
	std::vector<TreeViewItem*>::iterator itr = m_items.begin();
	std::vector<TreeViewItem*>::iterator end = m_items.end();

	for( ; itr != end; ++itr)
		(*itr)->_UnhighlightExcept(pItem);
}

void TreeViewItem::_UnhighlightExcept(TreeViewItem* pItem)
{
	if(m_isHighlighted && this != pItem)
		m_isHighlighted = false;

	std::set<TreeViewItem*>::iterator itr = m_subItems.begin();
	std::set<TreeViewItem*>::iterator end = m_subItems.end();

	for(; itr != end; ++itr)
		(*itr)->_UnhighlightExcept(pItem);
}